package io.boot.modules.activiti.service.impl;

import cn.hutool.core.convert.Convert;
import io.boot.common.utils.PageUtils;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

@Service
public class ProcessDefinitionService {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private IdentityService identityService;


    public List<Task> getTasks(String assignee) {
        return taskService.createTaskQuery().taskAssignee(assignee).list();
    }

    @Transactional
    public void deployProcessDefinition(String filePath) throws FileNotFoundException {
        if (StringUtils.isNotBlank(filePath)) {
            if (filePath.endsWith(".zip")) {
                ZipInputStream inputStream = new ZipInputStream(new FileInputStream(filePath));
                repositoryService.createDeployment()
                        .addZipInputStream(inputStream)
                        .deploy();
            } else if (filePath.endsWith(".bpmn")) {
                repositoryService.createDeployment()
                        .addInputStream(filePath, new FileInputStream(filePath))
                        .deploy();
            }
        }
    }

    @Transactional
    public void deleteProcessDeploymentByIds(String deploymentIds) {
        String[] deploymentIdsArr = Convert.toStrArray(deploymentIds);
        for (String deploymentId: deploymentIdsArr) {
            List<ProcessInstance> instanceList = runtimeService.createProcessInstanceQuery()
                    .deploymentId(deploymentId)
                    .list();
//            if (!CollectionUtils.isEmpty(instanceList)) continue;   // 跳过存在流程实例的流程定义
            repositoryService.deleteDeployment(deploymentId, true); // true 表示级联删除引用，比如 act_ru_execution 数据
        }
    }

    /**
     * 分页查询流程定义文件
     * @return
     */
    public PageUtils queryPage(Map<String, Object> params) {
        Integer page=Integer.valueOf(params.get("page").toString());
        Integer limit=Integer.valueOf(params.get("limit").toString());

        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        processDefinitionQuery.orderByProcessDefinitionId().orderByProcessDefinitionVersion().desc();
        if (params.get("name")!=null) {
            processDefinitionQuery.processDefinitionNameLike("%" + params.get("name").toString() + "%");
        }
        if (params.get("key")!=null) {
            processDefinitionQuery.processDefinitionKeyLike("%" + params.get("key").toString() + "%");
        }
        if (params.get("category")!=null) {
            processDefinitionQuery.processDefinitionCategoryLike("%" + params.get("category").toString() + "%");
        }

        List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage((page - 1) * limit, limit);
        List<io.boot.modules.activiti.dto.ProcessDefinition> list=new ArrayList<>();
        for (ProcessDefinition definition: processDefinitionList) {
            io.boot.modules.activiti.dto.ProcessDefinition entity = new io.boot.modules.activiti.dto.ProcessDefinition();
            entity.setId(definition.getId());
            entity.setKey(definition.getKey());
            entity.setCategory(definition.getCategory());
            entity.setVersion(definition.getVersion());
            entity.setDescription(definition.getDescription());
            entity.setDeploymentId(definition.getDeploymentId());
            Deployment deployment = repositoryService.createDeploymentQuery()
                    .deploymentId(definition.getDeploymentId())
                    .singleResult();
            entity.setName(deployment.getName());
            entity.setDeploymentTime(deployment.getDeploymentTime());
            entity.setType(definition.isSuspended());
            entity.setDefinitId(definition.getId());
            list.add(entity);
        }


        PageUtils pages =new PageUtils(list,Integer.valueOf(processDefinitionQuery.count()+""),page,limit);
        return pages;
    }
}
